package com.sakura.taos.tool.manipulator.controllers;

import com.baomidou.dynamic.datasource.DynamicRoutingDataSource;
import com.baomidou.dynamic.datasource.creator.HikariDataSourceCreator;
import com.baomidou.dynamic.datasource.ds.GroupDataSource;
import com.baomidou.dynamic.datasource.spring.boot.autoconfigure.DataSourceProperty;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sakura.taos.tool.manipulator.model.DataBaseNews;
import com.sakura.taos.tool.manipulator.model.LayuiTree;
import com.sakura.taos.tool.manipulator.model.MyDataSource;
import com.sakura.taos.tool.manipulator.model.SysDbLink;
import com.sakura.taos.tool.manipulator.model.layui.LayReturn;
import com.sakura.taos.tool.manipulator.model.layui.LayReturnToData;
import com.sakura.taos.tool.manipulator.model.layui.LayReturnToTidings;
import com.sakura.taos.tool.manipulator.model.layui.LayuPage;
import com.sakura.taos.tool.manipulator.service.SysDbLinkService;
import com.sakura.taos.tool.manipulator.service.TaosSysService;
import com.sakura.taos.tool.manipulator.tool.Cache;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import javax.annotation.Resource;
import javax.sql.DataSource;
import java.util.*;

import static com.sakura.taos.tool.manipulator.conf.ConstantConf.DATA_BASE_GROUP_MAIN_NAME;
import static com.sakura.taos.tool.manipulator.conf.ConstantConf.DATA_BASE_GROUP_SEPARATOR;
import static com.sakura.taos.tool.manipulator.tool.Tool.stringIsNull;

/**
 * 事件源管理类
 *
 * @Author: 贺坤
 * @Date: 2021/1/28 20:15
 */
@RestController
@RequestMapping("/dataSource")
@ResponseBody
public class TaosDataSourceController {

    //    @Autowired
//    @Qualifier("dataSource")
    @Resource
    private DynamicRoutingDataSource dataSource;
    @Autowired
    private HikariDataSourceCreator hikariDataSourceCreator;
    @Autowired
    private SysDbLinkService sysDbLinkService;
    @Autowired
    private TaosSysService taosSysService;
    @Autowired
    private Cache cache;

    /**
     * 添加数据源
     *
     * @param sysDbLink
     */
    @PostMapping
    public LayReturn save(SysDbLink sysDbLink) {
        if (sysDbLink.getId() == null) {
            boolean save = sysDbLinkService.save(sysDbLink);
            return save ? new LayReturn(0, "添加成功") : new LayReturn(-1, "添加" + sysDbLink.getHostname() + "事件源失败");
        } else {
            boolean save = sysDbLinkService.updateById(sysDbLink);
            return save ? new LayReturn(0, "编辑成功") : new LayReturn(-1, "编辑" + sysDbLink.getHostname() + "事件源失败");
        }

    }

    /**
     * 获取所有连接信息
     *
     * @param hostname 连接名称
     * @param connect  链接状态条件
     * @param layuPage 分页条件
     * @return
     */
    @GetMapping
    public LayReturnToData<SysDbLink> getList(String hostname, Boolean connect, LayuPage<SysDbLink> layuPage) {
        QueryWrapper queryWrapper = new QueryWrapper();
        queryWrapper.like(stringIsNull(hostname), "hostname", hostname);
        Page page = sysDbLinkService.page(layuPage.getMybatisPlusPage(), queryWrapper);
        List<SysDbLink> records = page.getRecords();

        sysDbLinkService.connectionStatusCensor(records);
        LayReturnToData layReturnToData = new LayReturnToData(page, records);
        return layReturnToData;
    }

    /**
     * 判断hostname 是否重复
     * @param hostname
     * @return
     */
    @GetMapping("hostname")
    public LayReturnToTidings hostname(String hostname) {
        QueryWrapper<SysDbLink> query = new QueryWrapper();
        query.eq("hostname",hostname);
        List<SysDbLink> list = sysDbLinkService.list(query);
        LayReturnToTidings layReturn  = new LayReturnToTidings(list.size()==0);
        return layReturn;
    }

    @DeleteMapping
    public LayReturn removeByIds(String[] idList) {
        List<String> ids = Arrays.asList(idList);
        boolean b = sysDbLinkService.removeByIds(ids);
        return b ? new LayReturn(0, "成功删除") : new LayReturn(500, "删除失败" + ids.size() + "条数据");
    }

    /**
     * 操作连接 开启或关闭连接
     *
     * @param connect true 开启连接  false 断开连接
     * @param id      需要操作的连接ID
     * @return
     */
    @PostMapping("{id}")
    public LayReturn operationConnection(Boolean connect, @PathVariable Long id) {
        SysDbLink sysDbLink = sysDbLinkService.getById(id);
        if (connect) {
            try {
                DataSourceProperty dataSourceProperty = new DataSourceProperty();
                MyDataSource dto = sysDbLink.getDataSource();
                BeanUtils.copyProperties(dto, dataSourceProperty);
                //使用hikari 连接池管理
                DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
                this.dataSource.addDataSource(dto.getPollName(), dataSource);
            } catch (Exception e) {
                //表示连接失败
                return new LayReturn(500, e.getMessage() + "\r\n 数据库连接异常,请检查");
            }
            // 表示连接成功
            // 添加到缓存记录
            cache.getMap().put(sysDbLink.getHostname(),sysDbLink);
            List<DataBaseNews> databases = taosSysService.getDatabases(sysDbLink.computePollName());
            // 添加库连接
            for (DataBaseNews base : databases) {
                sysDbLink.setDataBaseName(base.getName());
                MyDataSource dto = sysDbLink.getDataSource();
                DataSourceProperty dataSourceProperty = new DataSourceProperty();
                BeanUtils.copyProperties(dto, dataSourceProperty);
                DataSource dataSource = hikariDataSourceCreator.createDataSource(dataSourceProperty);
                this.dataSource.addDataSource(dto.getPollName(), dataSource);
            }
            return new LayReturn(0, "成功");
        } else {
            // 从缓存中删除
            cache.getMap().keySet().removeIf(key -> key.equals(sysDbLink.getHostname()));
            String pollName = sysDbLink.computePollName();
            String group = pollName.split(DATA_BASE_GROUP_SEPARATOR)[0];
            GroupDataSource groupDataSource = this.dataSource.getCurrentGroupDataSources().get(group);
            Set<String> keys = groupDataSource.getDataSourceMap().keySet();
            for (String key : keys) {
                this.dataSource.removeDataSource(key);
            }
            return new LayReturn(0, "关闭成功");
        }
    }


}
